home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / CUGUK / COMMS / C035.ZIP / JMODEM_D.C < prev    next >
Text File  |  1990-02-17  |  9KB  |  163 lines

  1. /****************************************************************************/
  2. /*   FILE JMODEM_D.C                                                        */
  3. /*   Created 11-JAN-1990                  Richard B. Johnson                */
  4. /*                                        405 Broughton Drive               */
  5. /*                                        Beverly, Massachusetts 01915      */
  6. /*                                        BBS (508) 922-3166                */
  7. /*                                                                          */
  8. /*   disp();        (Displays a "USAGE" message)                            */
  9. /*   encode();      (Data compression routine  )                            */
  10. /*   decode();      (Data expansion routine    )                            */
  11. /*   calc_crc();    (CRC checking and setting  )                            */
  12. /*                                                                          */
  13. /****************************************************************************/
  14. #include <stdio.h>                              /* For _printf()            */
  15. #include <stdlib.h>                             /* For _rotl()              */
  16. #include "jmodem.h"                             /* JMODEM primatives        */
  17. #pragma intrinsic (_rotl)
  18. /****************************************************************************/
  19. /*                          Print the 'Usage' prompt.                       */
  20. /****************************************************************************/
  21. void disp()
  22. {
  23.     unsigned short i;
  24.     printf("\nUsage:");
  25.     for (i=1; i < 5; i++)
  26.         printf("\nJMODEM S%d FILENAME.TYP < Send a file using COM%d  >",i,i);
  27.     for (i=1; i < 5; i++)
  28.         printf("\nJMODEM R%d FILENAME.TYP <Receive a file using COM%d>",i,i);
  29.     return;
  30. }
  31. /****************************************************************************/
  32. /*                   Encode (compress) the input string.                    */
  33. /*   The routine looks for groups of identical characters and replaces them */
  34. /*   with the character  0xBB, a word denoting the number of characters to  */
  35. /*   duplicate, followed by the character to duplicate.                     */
  36. /*                                                                          */
  37. /****************************************************************************/
  38.  
  39. unsigned short encode(len, in_buffer, out_buffer)
  40. unsigned short len;                     /* Length of input string           */
  41. unsigned char *in_buffer;               /* Pointer to input buffer          */
  42. unsigned char *out_buffer;              /* Pointer to outpup buffer         */
  43. {
  44.     register unsigned short i=0;
  45.     register unsigned short j=0;
  46.     unsigned char c;                    /* Character to replace             */
  47.     unsigned char *in_limit;            /* End of the input string          */
  48.     unsigned char *out_limit;           /* End of the output buffer         */
  49.  
  50.     in_limit = in_buffer + len;         /* Calc buffer end only once        */
  51.     out_limit = out_buffer + DAT_LEN;   /* Calculate output buffer once     */
  52.     while (in_buffer < in_limit)        /* While more bytes in the buffer   */
  53.     {
  54.         if (out_buffer > out_limit)     /* If we exceeded the buffer size   */
  55.             return JM_MAX;              /* Show no compression possible     */
  56.         if (*in_buffer == 0xBB || *in_buffer == *(in_buffer+1) )
  57.         {
  58.             *out_buffer++ = 0xBB;       /* Insert token, bump pointer       */
  59.             c = *in_buffer;             /* Save duplicate character         */
  60.             i = 0;                      /* Start duplicate char count       */
  61.             while (*in_buffer++ == c)   /* Count occurances of duplicates   */
  62.                 i++;                    /* Count identical characters       */
  63.             in_buffer--;                /* Backup to dissimilar character   */
  64.             *out_buffer++ =
  65.                (unsigned char) i;       /* Character count, low byte        */
  66.             *out_buffer++ =
  67.               (unsigned char) (i >> 8); /* Character count, high byte       */
  68.             *out_buffer++ = c;          /* The duplicate character          */
  69.             j += 4;                     /* Adjust char count                */
  70.         }
  71.         else                            /* Else, just copy                  */
  72.         {
  73.             *out_buffer++ = *in_buffer++;
  74.             j++;                        /* Character count                  */
  75.         }
  76.     }
  77.     return j;                           /* New length                       */
  78. }
  79. /****************************************************************************/
  80. /*                     Decode (expand) the encoded string.                  */
  81. /*    Routine checks for a sentinel byte, 0xBB, and if found, takes the     */
  82. /*    following word as the number of identical bytes to add. The actual    */
  83. /*    byte to add is located following the length-word.                     */
  84. /*                                                                          */
  85. /****************************************************************************/
  86. unsigned short decode(len, in_buffer, out_buffer)
  87. unsigned short len;                             /* Length to input string   */
  88. unsigned char *in_buffer;                       /* Pointer to input buffer  */
  89. unsigned char *out_buffer;                      /* Pointer to output buffer */
  90. {
  91.     register unsigned short i=0;
  92.     register unsigned short j=0;
  93.     unsigned char c;
  94.     unsigned char *limit;                       /* Length of input buffer   */
  95.  
  96.     limit = in_buffer + len;                    /* Set end pointer once     */
  97.         while (in_buffer < limit)
  98.     {
  99.         if (*in_buffer == 0xBB )                /* If the sentinel byte     */
  100.         {
  101.              in_buffer ++;                      /* Next character           */
  102.              i = (unsigned short) *in_buffer++; /* Get low byte, incr       */
  103.              i = i | (unsigned short)
  104.                  (*in_buffer++) << 8;           /* Get high byte, incr      */
  105.              c = *in_buffer++;                  /* Get byte, incr           */
  106.              for ( ; i >0; i--)                 /* Don't alter i at start   */
  107.              {
  108.                  *out_buffer++ = c;             /* Expand byte              */
  109.                  j++;                           /* Character count          */
  110.              }
  111.         }
  112.         else                                    /* Else, just copy          */
  113.         {
  114.             *out_buffer++ = *in_buffer++;
  115.             j++;                                /* Character count          */
  116.         }
  117.     }
  118.     return j;                                   /* New string length        */
  119. }
  120. /****************************************************************************/
  121. /*                  Calculate the simple JMODEM CRC                         */
  122. /*    Routine obtains a pointer to the buffer of characters to be checked.  */
  123. /*    The first passed parameter is the length of the buffer. The CRC is    */
  124. /*    returned.                                                             */
  125. /*                                                                          */
  126. /****************************************************************************/
  127. unsigned short calc_crc(command, length, buffer)
  128. unsigned short command;                     /* Set or Check CRC             */
  129. unsigned short length;                      /* Buffer length                */
  130. unsigned char *buffer;                      /* Pointer to the buffer        */
  131. {
  132.     register unsigned short crc=0;          /* Start at zero                */
  133.     register unsigned short i;              /* Byte count                   */
  134.  
  135.     length -=2;                             /* Don't CRC the CRC            */
  136.     do
  137.     {
  138.     crc += (unsigned short) *buffer++;      /* Sum first                    */
  139.     i = length & 0x07;                      /* 7 bits max to rotate         */
  140.     crc  = _rotl(crc,i);                    /* Rotate i bits left           */
  141.     } while (--length);
  142.  
  143.     switch (command)
  144.     {
  145.         case GET_CRC:
  146.         {
  147.             i = (unsigned short) *buffer++;
  148.             i = i |  (unsigned short) (*buffer << 8 );
  149.             return (crc - i);               /* Return AX = 0 if CRC okay    */
  150.         }
  151.         case SET_CRC:
  152.         {
  153.             *buffer++ = (unsigned char) crc;
  154.             *buffer   = (unsigned char) (crc >> 8);
  155.             return crc;                     /* Return CRC though ignored    */
  156.         }
  157.         default:
  158.             return JM_MAX;                  /* Bad data, buffer overflow    */
  159.     }
  160. }
  161. /****************************************************************************/
  162. /************************ E N D  O F   M O D U L E **************************/
  163.